home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 1 / QRZ Ham Radio Callsign Database - December 1993.iso / ucsd / packet / tcpip / net / netamsrc.arc / mac_at.c < prev    next >
Encoding:
C/C++ Source or Header  |  1988-02-12  |  12.9 KB  |  590 lines

  1. /*
  2.  * This file contains the code for using the AppleTalk network.  This is a 
  3.  * first cut and hopefully it will work.
  4.  *
  5.  * This code is Copyright (C) 1987, by Mikel Matthews, N9DVG, All Rights Reserved.
  6.  * Permission granted for non-commercial copying and use, provided
  7.  * this notice is retained.
  8.  */
  9.  
  10.  
  11. #include <stdio.h>
  12. #include "global.h"
  13. #include "mbuf.h"
  14. #include "iface.h"
  15. #include "timer.h"
  16. #include "ip.h"
  17. #include "arp.h"
  18. #include <MacTypes.h>
  19. #include <Appletalk.h>
  20. #include "mac_AT.h"
  21. #include "trace.h"
  22.  
  23. struct at at[AT_MAX];        /* Per-controller info */
  24.  
  25. char appletalk_bdcst = 0xff;    /* all devices will read this address */
  26.  
  27. #ifdef    TRACE
  28. #include "trace.h"
  29. int at_dump();
  30. extern trace;
  31. #endif    TRACE
  32. unsigned    nat = 0;        /* Number of apple talk devices */
  33.     
  34. /* Initialize interface */
  35. at_init(interface,bufsize)
  36. struct interface *interface;
  37. unsigned bufsize;    /* Maximum size of receive queue in PACKETS */
  38. {
  39.     register struct at *atp;
  40.     int16 dev;
  41.     char *malloc();
  42.     int err;
  43.     ABRecPtr abrrdptr;
  44.     ABRecPtr abrwrptr;
  45.     int node, net;        /* vars to hold my node id and net id */
  46.     
  47. #ifdef DEBUG
  48.     printf("at_init called\n");
  49. #endif
  50.     dev = interface->dev;
  51.     /* 
  52.      * this check is only here because I sometimes get a little parinoid
  53.      */
  54.      
  55.     if ( dev >= nat )    
  56.     {
  57.         printf("problem with dev entry.  Number is  %d, max = %d\n", dev,nat);
  58.         return(-1);
  59.     }
  60.     atp = &at[dev];
  61.     atp->rcvmax = bufsize;
  62.     /*
  63.      * see if the device is available for use with AppleTalk
  64.      */
  65.     err = MPPOpen();
  66.     if ( err != noErr )
  67.     {
  68.         printf("AppleTalk is not available on device  error %d\n", err);
  69.         return(-1);
  70.     }
  71.  
  72.     /*
  73.      * See if we can put our protocol type in and have the default handler use it
  74.      */
  75.     err = LAPOpenProtocol(atp->ProtoType, NULL);
  76.     if ( err != noErr)
  77.     {
  78.         /*
  79.          * In case we bombed out last time, try and remove the protocol type and try again
  80.          */
  81.         if ( LAPCloseProtocol(atp->ProtoType) != 0 )
  82.         {
  83.  
  84.             printf("Could not initialize AppleTalk with protocol type %d, error %d\n",
  85.                  atp->ProtoType, err);
  86.             return(-1);
  87.         }
  88.         err = LAPOpenProtocol(atp->ProtoType, NULL);
  89.         if ( err != noErr)
  90.         {
  91.             printf("Could not initialize AppleTalk with protocol type %d, error %d\n",
  92.                  atp->ProtoType, err);
  93.             return(-1);
  94.         }
  95.     }
  96.     /*
  97.      * Since everything is alright, lets allocate an ABusRecord
  98.      */
  99.     
  100.     atp->rdATptr = NewHandle(lapSize);
  101.     if ( atp->rdATptr == NULL)
  102.     {
  103.         printf("Could not allocate handel for AppleBuss (0).\n");
  104.         (void)LAPCloseProtocol(atp->ProtoType);
  105.         return(-1);
  106.     }
  107.  
  108.     atp->wrATptr = NewHandle(lapSize);
  109.     
  110.     if ( atp->wrATptr == NULL)
  111.     {
  112.         printf("Could not allocate handel for AppleBuss (1).\n");
  113.         DisposHandle(atp->rdATptr);
  114.         (void)LAPCloseProtocol(atp->ProtoType);
  115.         return(-1);
  116.     }
  117.     
  118.     /*
  119.      * now that everything is going well, let's issue an async read on the protocol
  120.      */
  121.     HLock(atp->rdATptr);
  122.     HLock(atp->wrATptr);
  123.     abrrdptr = *atp->rdATptr;
  124.     abrwrptr = *atp->wrATptr;
  125.     
  126.     abrwrptr->lapProto.lapAddress.lapProtType = atp->ProtoType;
  127.     if ( at_startread(atp, abrrdptr) != 0 )
  128.     {
  129.         printf("Could not perform read on AppleTalk network.  Closing down device.\n");
  130.         return(-1);
  131.     }
  132.     /*
  133.      * This subroutine will return a unique node address
  134.      */
  135.     if ( GetNodeAddress( &node, &net) != 0)
  136.     {
  137.         printf("Could not get my own node address.  Something is wrong!!\n");
  138.         return(-1);
  139.     }
  140.     /*
  141.      * set up the hardware address in the interface struct
  142.      */
  143.     if ( interface->hwaddr == NULLCHAR )
  144.     {
  145.         if ( (interface -> hwaddr = malloc(4)) == NULLCHAR)
  146.         {
  147.             printf("Could not allocate memory for hardware address.\n");
  148.             return(-1);
  149.         }
  150.     }
  151.         
  152.     *interface->hwaddr = (unsigned char) node;
  153. /*    printf("My AppleTalk node number is %d\n", node);    */
  154.     return(0);
  155. }
  156.  
  157. /* Send an IP datagram on AppleTalk */
  158. at_send(bp,interface,gateway,precedence,delay,throughput,reliability)
  159. struct mbuf *bp;        /* Buffer to send */
  160. struct interface *interface;    /* Pointer to interface control block */
  161. int32 gateway;            /* IP address of next hop */
  162. char precedence;
  163. char delay;
  164. char throughput;
  165. char reliability;
  166. {
  167.     char *egate,*res_arp();
  168.     egate = res_arp(interface,ARP_APPLETALK,gateway,bp);
  169.     if(egate != NULLCHAR)
  170.     {
  171.         (*interface->output)(interface,egate,interface->hwaddr,AIP_TYPE,bp);
  172.     }
  173. }
  174.  
  175. /* Send a packet with Ethernet header */
  176. at_output(interface,dest,source,type,bp)
  177. struct interface *interface;        /* Pointer to interface control block */
  178. char dest[];        /* Destination Ethernet address */
  179. char source[];        /* Source Appletalk address */
  180. int16 type;        /* Type field */
  181. struct mbuf *bp;    /* Data field */
  182. {
  183.     struct    appletalk ap;    /* AppleTalk struct for header info. */
  184.     struct    mbuf    *hdr;
  185.     struct    mbuf    *htonat();
  186.  
  187.     memcpy(&ap.source, source, APPLE_LEN);
  188.     memcpy(&ap.dest, dest, APPLE_LEN);
  189.     ap.type = type;
  190.     hdr = htonat(&ap);
  191.     hdr->next = bp;
  192.     (*interface->raw)(interface,hdr);
  193. }
  194.  
  195. /* Send raw packet (caller provides header) */
  196. at_raw(interface,bp)
  197. struct interface *interface;        /* Pointer to interface control block */
  198. struct mbuf *bp;    /* Data field */
  199. {
  200.     register struct at *atp;    /* AppleTalk pointer */
  201.     short size;                    /* size of data in mbuf */
  202.     int err;                    /* error indicator from mac stuff */
  203.     short    tmp=2;                /* there is an offset of 2 in the data buffer */
  204.     short *mptr;                /* temporary pointer */
  205.     ABRecPtr abrwrptr;            /* pointer to applebuss record */
  206.     struct appletalk ap;        /* appletalk struct for front of record */
  207.     struct mbuf    *hdr;            /* extra mbuf pointer */
  208.     
  209.     atp = &at[interface->dev];
  210.     if ( interface->dev >= nat )
  211.     {
  212.         printf("problem with dev entry.  Number is  %d, max = %d\n", interface->dev,nat);
  213.         return(-1);
  214.     }
  215.     dump(interface,IF_TRACE_OUT,TRACE_APPLETALK,bp);
  216.     size = len_mbuf(bp);
  217.     
  218.     /*
  219.      * Set up the transmit structure
  220.      * take a part to get the address
  221.      */
  222.     ntohat(&ap, &bp);
  223.     abrwrptr = *atp->wrATptr;
  224.     abrwrptr->lapProto.lapAddress.dstNodeID = ap.dest;
  225.     abrwrptr->lapProto.lapDataPtr = atp->buffer;
  226.     abrwrptr->lapProto.lapAddress.lapProtType = atp->ProtoType;
  227.     
  228.     /*
  229.      * now put header back on
  230.      */
  231.      
  232.     hdr = htonat(&ap);
  233.     hdr->next = bp;
  234.  
  235.     /*
  236.         Copy all the data from the mbuf to the data packet holder.
  237.         Max amount of data is 600 bytes
  238.      */
  239.     while  ( hdr != NULLBUF)
  240.     {
  241.         bcopy(hdr->data, &abrwrptr->lapProto.lapDataPtr[tmp], hdr->cnt);
  242.         tmp += hdr->cnt;
  243.         if ( tmp >= 600)
  244.             printf("sending: ERROR IN PACKET SIZE, size = %d\n", tmp);
  245.  
  246.         hdr = free_mbuf(hdr);
  247.     }
  248.  
  249.     /* 
  250.         set the packet length in the first two bytes of the LAP data buffer
  251.         including these two bytes.
  252.      */
  253.      
  254.     mptr = abrwrptr->lapProto.lapDataPtr;
  255.     *mptr = tmp;
  256.     
  257.     abrwrptr->lapProto.lapReqCount = tmp;
  258.     
  259.     atp->astats.out++;
  260.     
  261.     /* send off a sync write and wait for return value. */
  262.     
  263.     err = LAPWrite(atp->wrATptr, FALSE);
  264.     
  265.     if ( err != noErr )
  266.     {
  267.         printf("at_raw: write failure to AppleTalk (%d)\n", err);
  268.         return(0);
  269.     }
  270. }
  271.  
  272. /* Process any incoming AppleTalk packets on the receive queue */
  273. int
  274. at_recv(interface)
  275. struct interface *interface;
  276. {
  277.     struct at *atp;            /* appletalk pointer */
  278.     struct mbuf *bp;        /* place to store all the buffers */
  279.     ABRecPtr abrrdptr;        /* Appletalk network storage */
  280.     int    err;
  281.     extern int32 ip_addr;
  282.     struct appletalk ap;
  283.     struct mbuf *htonat();
  284.     
  285.     /*
  286.      *  just to make sure it is for us
  287.      */
  288.  
  289.     atp = &at[interface->dev];
  290.     
  291.     if ( interface->dev >= nat )
  292.     {
  293.         printf("problem with dev entry.  Number is  %d, max = %d\n", interface->dev,nat);
  294.         return(-1);
  295.     }
  296.     
  297.     /*
  298.      * get a pointer to the read structure
  299.      */
  300.     
  301.     abrrdptr = *atp->rdATptr;
  302.     
  303.     /*
  304.      * since this was an async read, a 1 indicates it has not completed yet.
  305.      */
  306.  
  307.     if ( abrrdptr->lapProto.abResult == 1)
  308.     {
  309.         return;
  310.     }
  311.     else if  ( abrrdptr->lapProto.abResult == buf2SmallErr)
  312.     {
  313.         atp->astats.badsize++;
  314.         if ( at_startread(atp, abrrdptr ) != 0)
  315.         {
  316.             printf("Error in starting async read on appletalk network.\n");
  317.         }
  318.         return(-1);
  319.     }
  320.     else if  ( abrrdptr->lapProto.abResult == readQErr)
  321.     {
  322.         atp->astats.drop++;
  323.         if ( at_startread(atp, abrrdptr ) != 0)
  324.         {
  325.             printf("Error in starting async read on appletalk network.\n");
  326.         }
  327.         return(-1);
  328.     }
  329.     
  330.     /*
  331.      * now set up the mbuf. count -2 because AT puts in the count sent in the first two]
  332.      * bytes of the data.
  333.      */
  334.     
  335.     if((bp = alloc_mbuf(abrrdptr->lapProto.lapActCount-2)) == NULLBUF)
  336.     {
  337.         atp->astats.nomem++;
  338.         if ( at_startread(atp, abrrdptr ) != 0)
  339.         {
  340.             printf("Error in starting async read on appletalk network.\n");
  341.         }
  342.         return(-1);
  343.     }
  344.     
  345.     /*
  346.      * move it over
  347.      */
  348.  
  349.     bcopy(&abrrdptr->lapProto.lapDataPtr[2], bp->data, abrrdptr->lapProto.lapActCount-2);
  350.     
  351.     bp->cnt = abrrdptr->lapProto.lapActCount - 2;
  352.     
  353.     /* not start another async read on this device. */
  354.         
  355.     if ( at_startread(at, abrrdptr) != 0 )
  356.     {
  357.         printf("Could not perform read on AppleTalk network.  Closing down device.\n");
  358.         return(-1);
  359.     }
  360.     ntohat(&ap, &bp);
  361.     
  362.     switch (ap.type)
  363.     {
  364.     
  365.         case AARP_TYPE:
  366.             arp_input(interface, bp);
  367.              atp->astats.any++;
  368.             break;
  369.         
  370.         case AIP_TYPE:
  371.             ip_route(bp, 0);
  372.              atp->astats.any++;
  373.             break;
  374.             
  375.         default:
  376.         /*
  377.             printf("at_recv: wrong type (%x)\n", ap.type);
  378.          */
  379.              atp->astats.badtype++;
  380.  
  381.              free_p(bp);
  382.             break;
  383.     }
  384. }
  385. /* Shut down the Ethernet controller */
  386. at_stop(interface)
  387. struct interface *interface;
  388. {
  389.     int16 dev;
  390.     struct at *atp;
  391.  
  392. #ifdef DEBUG
  393.     printf("at_stop called. dev = %d\n", interface->dev);
  394. #endif
  395.  
  396.     dev = interface->dev;
  397.     if ( dev >= nat)
  398.         return(-1);
  399.     atp = &at[dev];
  400.     
  401.     /* need to unlock the frozen pointers and cancel any reads outstanding */
  402.  
  403.     (void)HUnlock(atp->rdATptr);
  404.     (void)HUnlock(atp->wrATptr);
  405.     (void)LAPRdCancel(atp->rdATptr);
  406.  
  407.     /* make sure to close the procotol down and dispose or any pointers */
  408.     
  409.     (void)LAPCloseProtocol(atp->ProtoType);
  410.     (void)DisposHandle(atp->rdATptr);
  411.     (void)DisposHandle(atp->wrATptr);
  412.  
  413.     return(0);
  414. }
  415. /* Attach AppleTalk to the system
  416.  * argv[0]: hardware type, must be "0"
  417.  * argv[1]: Protocol Type, e.g., "77"
  418.  * argv[2]: device name,must be "B"
  419.  * argv[3]: mode, must be "arpa"
  420.  * argv[4]: interface label, e.g., "at0"
  421.  * argv[5]: maximum number of packets allowed on receive queue, e.g., "5"
  422.  * argv[6]: maximum transmission unit, bytes, e.g., "600" < appletalk limitation.
  423.  */
  424. at_attach(argc,argv)
  425. int argc;
  426. char *argv[];
  427. {
  428.     register struct interface *if_at;
  429.     extern struct interface *ifaces;
  430.     unsigned dev;
  431.     char *calloc(),*malloc();
  432.     int at_init();
  433.     int at_send();
  434.     int at_recv();
  435.     int at_stop();
  436.     int err;
  437.     int pat(),gat();
  438.  
  439.     if(nat >= AT_MAX){
  440.         printf("Too many AppleTalk controllers\r\n");
  441.         return -1;
  442.     }
  443.     dev = nat++;
  444.     if_at = (struct interface *)calloc(1,sizeof(struct interface));
  445.  
  446.     if_at->name = malloc((unsigned)strlen(argv[4])+1);
  447.     strcpy(if_at->name,argv[4]);
  448.     if_at->mtu = atoi(argv[6]);
  449.     if_at->send = at_send;
  450.     if_at->output = at_output;
  451.     if_at->raw = at_raw;
  452.     if_at->recv = at_recv;
  453.     if_at->stop = at_stop;
  454.     if_at->dev = dev;
  455.     if_at->flags = 0;
  456.     at[dev].ProtoType = htoi(argv[1]);
  457.     at[dev].net = malloc(strlen(argv[2])+1);
  458.     strcpy(at[dev].net, argv[2]);
  459.  
  460.     if(strcmp(argv[3],"arpa") != 0){
  461.         printf("Mode %s unknown for interface %s\r\n",
  462.             argv[3],argv[4]);
  463.         free((char *)if_at);
  464.         return -1;
  465.     }
  466.     arp_init(ARP_APPLETALK,APPLE_LEN,AIP_TYPE,AARP_TYPE,appletalk_bdcst,pat,gat);
  467.     if_at->next = ifaces;
  468.     ifaces = if_at;
  469.     /* Initialize device */
  470.     if ( (err = at_init(if_at,(unsigned)atoi(argv[5]))) != 0 )
  471.     {
  472.         printf("AT_INIT failed. err = %d\n", err);
  473.         return(-1);
  474.     }
  475.     else
  476.     {
  477.         return 0;
  478.     }
  479. }
  480.  
  481. /*
  482.     this procedure will start up an async read on the appletalk network
  483.  */
  484.  
  485. at_startread(atp, readptr)
  486. struct at *atp;
  487. ABRecPtr readptr;
  488. {
  489.     int err;
  490.     
  491.     /*
  492.      * set up the structure for a read
  493.      */
  494.      
  495.     readptr->lapProto.lapAddress.lapProtType = atp->ProtoType;
  496.     readptr->lapProto.lapReqCount = MAX_ATBUF;
  497.     readptr->lapProto.lapDataPtr = atp->buffer;
  498.     
  499.     /*
  500.      * issue the read using the async flag
  501.      */
  502.  
  503.     err = LAPRead( atp->rdATptr, TRUE);
  504.     if ( err != noErr )
  505.     {
  506.         (void)LAPCloseProtocol(atp->ProtoType);
  507.         (void)DisposHandle(atp->rdATptr);
  508.         (void)DisposHandle(atp->wrATptr);
  509.         return(-1);
  510.     }            
  511.     return(0);
  512. }
  513.  
  514. bcopy(from, to, cnt)
  515. char *to, *from;
  516. int cnt;
  517. {
  518.     while ( cnt-- != 0 )
  519.     {
  520.         *to++ = *from++;
  521.     }
  522. }
  523. /* Format an AppleTalk address into a printable ascii string */
  524. pat(out,addr)
  525. char *out,*addr;
  526. {
  527.     sprintf(out,"%02x", *addr & 0xff);
  528. }
  529.  
  530. /* Convert an AppleTalk address from Hex/ASCII to binary */
  531. gat(out,cp)
  532. register char *out;
  533. register char *cp;
  534. {
  535.     register int i;
  536.  
  537.     *out = htoi(cp);
  538. }
  539.  
  540. /* Convert AppleTalk header in host form to network mbuf */
  541. struct mbuf *
  542. htonat(ap)
  543. struct appletalk *ap;
  544. {
  545.     struct mbuf *bp;
  546.     register char *cp;
  547.     bp = alloc_mbuf(APPLEADDRLEN);
  548.     bp->cnt = APPLEADDRLEN;
  549.     cp = bp->data;
  550.     memcpy(cp,&ap->dest,APPLE_LEN);
  551.     cp += APPLE_LEN;
  552.     memcpy(cp,&ap->source,APPLE_LEN);
  553.     cp += APPLE_LEN;
  554.     put16(cp,ap->type);
  555.  
  556.     return bp;
  557. }
  558. /* Extract AppleTalk header */
  559. ntohat(ap,bpp)
  560. struct appletalk *ap;
  561. struct mbuf **bpp;
  562. {
  563.     pullup(bpp,&ap->dest,APPLE_LEN);
  564.     pullup(bpp,&ap->source,APPLE_LEN);
  565.     ap->type = pull16(bpp);
  566.     return APPLEADDRLEN;
  567. }
  568.  
  569.  
  570.  
  571. int
  572. doatstat(argc,argv)
  573. int argc;
  574. char *argv[];
  575. {
  576.     struct at *atp;
  577.  
  578.     for(atp = at;atp <= &at[nat]; atp++){
  579.         
  580.         printf("Controller %u:\n",atp-at);
  581.  
  582.         printf("any      output    badtype   nomem     drop     badsize\n");
  583.         printf("%-10lu%-10lu%-10lu%-10lu%-10lu%-10lu\n",
  584.          atp->astats.any, atp->astats.out,
  585.          atp->astats.badtype, atp->astats.nomem,
  586.          atp->astats.drop, atp->astats.badsize);
  587.     }
  588.     return 0;
  589. }
  590.